#include "mysql_manager.hpp"
#include <stdexcept>
#include <mysql/mysql.h>
#include <sstream>
#include <iomanip>
#include <cstring>
#include <stdbool.h>

MysqlManager::MysqlManager(const MySQLConfig& config) {
    mysql_pool_ = std::make_unique<MySQLPool>(config);
    mysql_pool_->initialize();
}

// 高级查询接口
// std::vector<ResultRow> MysqlManager::query(const std::string& sql, 
//                                 const std::vector<std::any>& params) {
//     auto conn = mysql_pool_->get_connection();
//     if (!conn) {
//         throw std::runtime_error("Failed to get MySQL connection from pool");
//     }
    
//     // 准备查询
//     MYSQL_STMT* stmt = mysql_stmt_init(conn.get());
//     if (!stmt) {
//         throw std::runtime_error(std::string("Failed to initialize MySQL statement: ") + 
//                                mysql_error(conn.get()));
//     }
    
//     // 准备SQL语句
//     if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length()) != 0) {
//         std::string error = mysql_stmt_error(stmt);
//         mysql_stmt_close(stmt);
//         throw std::runtime_error("Failed to prepare MySQL statement: " + error);
//     }
    
//     // 绑定参数
//     bind_params(stmt, params);
    
//     // 执行查询
//     if (mysql_stmt_execute(stmt) != 0) {
//         std::string error = mysql_stmt_error(stmt);
//         mysql_stmt_close(stmt);
//         throw std::runtime_error("Failed to execute MySQL statement: " + error);
//     }
    
//     // 获取结果
//     std::vector<ResultRow> results = fetch_results(stmt);
    
//     // 清理
//     mysql_stmt_close(stmt);
    
//     return results;
// }

std::vector<ResultRow> MysqlManager::query(const std::string& sql, 
                    const std::vector<std::any>& params) {
    auto conn = mysql_pool_->get_connection();
    if (!conn) {
        throw std::runtime_error("Failed to get MySQL connection from pool");
    }

    // 直接查询，不通过mysql_stmt_init
    if (mysql_query(conn.get(), sql.c_str()) != 0) {
        throw std::runtime_error("Failed to query MySQL: " + std::string(mysql_error(conn.get())));
    }
    
    MYSQL_RES* res = mysql_store_result(conn.get());
    if (!res) {
        throw std::runtime_error("Failed to store result: " + std::string(mysql_error(conn.get())));
    }

    std::vector<ResultRow> results;
    
    MYSQL_ROW row;
    while ((row = mysql_fetch_row(res)) != nullptr) {
        ResultRow result_row;
        for (unsigned int i = 0; i < mysql_num_fields(res); i++) {
            result_row.set_value(mysql_fetch_field_direct(res, i)->name, row[i]);
        }
        results.push_back(result_row);
    }   

    mysql_free_result(res);

    return results;
}

int64_t MysqlManager::execute(const std::string& sql, 
                    const std::vector<std::any>& params) {
    auto conn = mysql_pool_->get_connection();
    if (!conn) {
        throw std::runtime_error("Failed to get MySQL connection from pool");
    }
    
    // 准备查询
    MYSQL_STMT* stmt = mysql_stmt_init(conn.get());
    if (!stmt) {
        throw std::runtime_error(std::string("Failed to initialize MySQL statement: ") + 
                               mysql_error(conn.get()));
    }
    
    // 准备SQL语句
    if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length()) != 0) {
        std::string error = mysql_stmt_error(stmt);
        mysql_stmt_close(stmt);
        throw std::runtime_error("Failed to prepare MySQL statement: " + error);
    }
    
    // 绑定参数
    bind_params(stmt, params);
    
    // 执行查询
    if (mysql_stmt_execute(stmt) != 0) {
        std::string error = mysql_stmt_error(stmt);
        mysql_stmt_close(stmt);
        throw std::runtime_error("Failed to execute MySQL statement: " + error);
    }
    
    // 获取影响的行数
    int64_t affected_rows = mysql_stmt_affected_rows(stmt);
    
    // 清理
    mysql_stmt_close(stmt);
    
    return affected_rows;
}

// 辅助方法：绑定参数
void MysqlManager::bind_params(MYSQL_STMT* stmt, const std::vector<std::any>& params) {
    if (params.empty()) {
        return;
    }
    
    // 获取参数数量
    unsigned int param_count = mysql_stmt_param_count(stmt);
    if (param_count != params.size()) {
        throw std::runtime_error("Parameter count mismatch: expected " + 
                               std::to_string(param_count) + ", got " + 
                               std::to_string(params.size()));
    }
    
    // 准备绑定参数
    std::vector<MYSQL_BIND> binds(param_count);
    std::vector<std::string> string_buffers; // 保持字符串生命周期
    std::vector<unsigned long> lengths;      // 字符串长度
    
    memset(binds.data(), 0, sizeof(MYSQL_BIND) * param_count);
    
    // 根据参数类型设置绑定
    for (unsigned int i = 0; i < param_count; i++) {
        const std::any& param = params[i];

        if (auto ptr = std::any_cast<int>(&param)) {    
            binds[i].buffer_type = MYSQL_TYPE_LONG;
            binds[i].buffer = (void*)ptr;
            binds[i].is_null = nullptr;
            binds[i].length = 0;
        }
        else if (auto ptr = std::any_cast<int64_t>(&param)) {
            binds[i].buffer_type = MYSQL_TYPE_LONGLONG;
            binds[i].buffer = (void*)ptr;
            binds[i].is_null = nullptr;
            binds[i].length = 0;
        }
        else if (auto ptr = std::any_cast<double>(&param)) {
            binds[i].buffer_type = MYSQL_TYPE_DOUBLE;
            binds[i].buffer = (void*)ptr;
            binds[i].is_null = nullptr;
            binds[i].length = 0;
            }
        else if (auto ptr = std::any_cast<std::string>(&param)) {
            string_buffers.push_back(*ptr); 
            lengths.push_back(ptr->length());

            
            binds[i].buffer_type = MYSQL_TYPE_STRING;
            binds[i].buffer = (void*)string_buffers.back().c_str();
            binds[i].buffer_length = string_buffers.back().length();
            binds[i].length = &lengths.back();
            binds[i].is_null = nullptr;
        }
        else {
            throw std::runtime_error(std::string("Unsupported parameter type: ") + param.type().name());
        }
        // else if (param.type() == typeid(int)) {
        //     binds[i].buffer_type = MYSQL_TYPE_LONG;
        //     binds[i].buffer = (void*)&(std::any_cast<int>(param));
        // } 
        // else if (param.type() == typeid(int64_t)) {
        //     binds[i].buffer_type = MYSQL_TYPE_LONGLONG;
        //     binds[i].buffer = (void*)&(std::any_cast<int64_t>(param));
        // }
        // else if (param.type() == typeid(double)) {
        //     binds[i].buffer_type = MYSQL_TYPE_DOUBLE;
        //     binds[i].buffer = (void*)&(std::any_cast<double>(param));
        // }
        // else if (param.type() == typeid(std::string)) {
        //     const std::string& str = std::any_cast<std::string>(param);
        //     string_buffers.push_back(str);
        //     lengths.push_back(str.length());
            
        //     binds[i].buffer_type = MYSQL_TYPE_STRING;
        //     binds[i].buffer = (void*)string_buffers.back().c_str();
        //     binds[i].buffer_length = string_buffers.back().length();
        //     binds[i].length = &lengths.back();
        // }
        // // 可以添加更多类型的支持
        // else if (param.type() == typeid(bool)) {
        //     binds[i].buffer_type = MYSQL_TYPE_TINY;
        //     binds[i].buffer = (void*)&(std::any_cast<bool>(param));
        // }
        // else if (param.type() == typeid(float)) {
        //     binds[i].buffer_type = MYSQL_TYPE_FLOAT;
        //     binds[i].buffer = (void*)&(std::any_cast<float>(param));
        // }
        // else {
        //     throw std::runtime_error("Unsupported parameter type: " + param.type().name());
        // }
    }
    
    // 绑定参数
    if (mysql_stmt_bind_param(stmt, binds.data()) != 0) {
        throw std::runtime_error(std::string("Failed to bind parameters: ") + 
                               mysql_stmt_error(stmt));
    }
}

// 辅助方法：获取结果
std::vector<ResultRow> MysqlManager::fetch_results(MYSQL_STMT* stmt) {
    std::vector<ResultRow> results;
    
    // 获取结果元数据
    MYSQL_RES* metadata = mysql_stmt_result_metadata(stmt);
    if (!metadata) {
        // 可能是INSERT/UPDATE/DELETE语句，没有结果集
        return results;
    }
    
    // 获取字段数
    unsigned int num_fields = mysql_num_fields(metadata);
    
    // 获取字段信息
    MYSQL_FIELD* fields = mysql_fetch_fields(metadata);
    
    // 准备绑定结果
    std::vector<char> is_nulls(num_fields);
    std::vector<MYSQL_BIND> binds(num_fields);
    std::vector<unsigned long> lengths(num_fields);
    std::vector<std::vector<char>> buffers(num_fields, std::vector<char>(1024)); // 每个字段1024字节的缓冲区
    
    memset(binds.data(), 0, sizeof(MYSQL_BIND) * num_fields);
    
    // 设置绑定
    for (unsigned int i = 0; i < num_fields; i++) {
        binds[i].buffer_type = MYSQL_TYPE_STRING;
        binds[i].buffer = buffers[i].data();
        binds[i].buffer_length = buffers[i].size() - 1; // 留一个字节给\0
        binds[i].is_null = reinterpret_cast<bool*>(&is_nulls[i]);  // Cast to bool*
        binds[i].length = &lengths[i];
    }
    
    // 绑定结果
    if (mysql_stmt_bind_result(stmt, binds.data()) != 0) {
        std::string error = mysql_stmt_error(stmt);
        mysql_free_result(metadata);
        throw std::runtime_error("Failed to bind result: " + error);
    }
    
    // 获取结果
    while (mysql_stmt_fetch(stmt) == 0) {
        ResultRow row;
        
        // 填充行数据
        for (unsigned int i = 0; i < num_fields; i++) {
            std::string column_name = fields[i].name;
            
            if (is_nulls[i]) {
                // 字段为NULL
                row.set_null(column_name);
            } else {
                // 确保缓冲区以\0结尾
                buffers[i][lengths[i]] = '\0';
                row.set_value(column_name, std::string(buffers[i].data(), lengths[i]));
            }
        }
        
        results.push_back(row);
    }
    
    // 清理
    mysql_free_result(metadata);
    
    return results;
}